﻿using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace Red.Toolkit.Profiler.Logic
{
    public class ProfilerTraceInstance
    {
        private bool _visible;
        private ulong _engineInstanceID;
        private string _name;
        private ObservableCollection<ProfilerDataView> _dataViews;
        private SortedDictionary<string, MergedGroup> _mergedGroups;

        public ProfilerTraceInstance( ulong engineInstanceID )
        {
            _visible = true;
            _engineInstanceID = engineInstanceID;
            _dataViews = new ObservableCollection<ProfilerDataView>();
            _mergedGroups = null;

            if ( engineInstanceID > 0 )
            {
                // based on red::DateTime
                uint time = (uint)engineInstanceID;
                uint date = (uint)(engineInstanceID >> 32);

                uint year = (date & 0xFFF00000) >> 20;
                uint month = ((date & 0x000F8000) >> 15) + 1;
                uint day = ((date & 0x00007C00) >> 10) + 1;

                uint hour = (time & 0x07C00000) >> 22;
                uint minute = ((time & 0x03F0000) >> 16);
                uint second = ((time & 0x0000FC00) >> 10);
                uint millisecond = time & 0x000003FF;

                _name = string.Format( "{0:D4}-{1:D2}-{2:D2} {3:D2}:{4:D2}:{5:D2}.{6:D3}",
                    year, month, day, hour, minute, second, millisecond );
            }
            else
                _name = "<UNKNOWN LAUNCH DATE>";
        }

        public ObservableCollection<ProfilerDataView> DataViews { get { return _dataViews; } set { _dataViews = value; } }
        public ulong EngineInstanceID { get { return _engineInstanceID; } }
        public SortedDictionary<string, MergedGroup> Groups { get { return _mergedGroups; } }
        public string Name { get { return _name; } }
        public bool Visible { get { return _visible; } set { _visible = value; } }

        // merge all visible views
        public void Prepare()
        {
            _mergedGroups = new SortedDictionary<string, MergedGroup>();

            foreach ( ProfilerDataView view in DataViews )
            {
                if ( !view.Visible )
                    continue;

                foreach ( Group g in view.Groups )
                {
                    if ( !g.Visible )
                        continue;

                    if ( !_mergedGroups.ContainsKey( g.Name ) )
                    {
                        MergedGroup newGroup = new MergedGroup( g.Name, g.StackStructure );
                        _mergedGroups.Add( g.Name, newGroup );
                    }

                    MergedGroup mergedGroup = _mergedGroups[g.Name];
                    mergedGroup.AddGroup( g );
                }
            }

            foreach ( var g in _mergedGroups )
                g.Value.Prepare();
        }

        // TODO: regex, disabling case-sensitivity, etc.
        public void SelectEventsContainingString( string str, ICollection<Event> selected )
        {
            foreach ( var group in Groups )
            {
                foreach ( var pair in group.Value.Levels )
                {
                    GroupLevel level = pair.Value;

                    if ( level.RootNode == null )
                        continue;

                    bool selectionChanged = false;
                    foreach ( var e in level.events )
                    {
                        string caption = e.Value.GetCaption();
                        if ( caption.Contains( str ) )
                        {
                            selectionChanged = true;
                            e.Value.Style = Event.DrawStyle.Normal;
                            selected.Add( e.Value );
                        }
                    }

                    if ( selectionChanged )
                        level.RootNode.UpdateSelectionRecursive();
                }
            }
        }
    }
}
